
package com.joysuch.wwyt.util;

import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

/**
 * Spring Bean 工具类
 */
public class SpringBeanUtils {

    private static final Logger logger = LoggerFactory.getLogger(SpringBeanUtils.class);

    /**
     * 通过 SpringBean 工具类方法复制原目标属性到目标对象
     * 
     * @param source
     * @param target
     * @param ignoreNull
     *                       是否忽略 Null property 值
     */
    public static void copyProperties(Object source, Object target, boolean ignoreNull) {
        if (ignoreNull) {
            BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
        } else {
            BeanUtils.copyProperties(source, target);
        }
    }

    /**
     * 获取Bean 对象 null 值属性名称列表
     * 
     * @param source
     * @return
     */
    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();
        Set<String> emptyNames = new HashSet<String>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null)
                emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 获取形如a.b.c多层次对象值, 首先从a对象中取b属性值，再从该值中取c属性值。如果有一环为null或属性不存在，返回null。
     * 
     * @param object
     * @param queryObjectParams
     * @return
     */
    public static Object extractChainValueFromArg(Object object, String queryObjectParams) {
        if (object == null) {
            return object;
        }
        int i = queryObjectParams.indexOf('.');
        if (i == -1) {
            return object;
        }
        String[] ladders = queryObjectParams.substring(i + 1).split(".");
        for (int j = 0; j < ladders.length; j++) {
            object = getChainPropertyValue(object, ladders[j]);
            if (object == null) {
                return null;
            }
        }
        // 获取链式值
        return object;
    }

    private static Object getChainPropertyValue(Object object, String substring) {
        PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(object.getClass(), substring);
        if (pd != null && pd.getReadMethod() != null) {
            try {
                return pd.getReadMethod().invoke(object, null);
            } catch (Exception e) {
                logger.error("获取属性值出错{}, {}", object, substring);
            }
        }
        return null;
    }

}
